package ks.server.controllers.commands.admin.user;

import java.util.Vector;

import ks.framework.common.Message;
import ks.framework.communicator.Communicator;
import ks.framework.interfaces.IProcessMessage;
import ks.managers.user.User;
import ks.server.controllers.requests.AckRequest;
import ks.server.controllers.requests.NackRequest;
import ks.server.persist.PersistentUserManager;
import ks.server.ServerContext;

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * Process request to create users.
 * 
 * @author Christopher Page
 */
public class UserCreateController implements IProcessMessage {

	/** Primary agent to whom we can communicate our messages. */
	Communicator com;
	
	public UserCreateController (Communicator com) {
		this.com = com;
	}
	
	/**
	 * Process the message
	 * 
	 * @param m The message to process.
	 * @return A boolean value.
	 */
	public boolean process(Message m) {
		String originator = m.getOriginator();
		
		if (originator == null) {
			System.err.println("Originator is null.");
			return false;
		}
		
		PersistentUserManager um = ServerContext.getUserManager();
		
		if (um.getUser(originator) == null || !um.getUser(originator).isAdmin()) {
			new NackRequest(com).send(m, 4, "Access denied.", originator);
			return false;
		}
		
		Node userCreateNode = m.contents();
		
		if (userCreateNode == null || !userCreateNode.getNodeName().equalsIgnoreCase("user-create")) {
			new NackRequest(com).send(m, 4, "Unable to find user-create element.", originator);
			return false;
		}
		
		NodeList accountInfoList = userCreateNode.getChildNodes();
		Node accountInfoNode;
		Node nameNode;
		Node passwordNode;
		
		Vector<User> toAdd = new Vector<User>();
		for (int i=0; i<accountInfoList.getLength(); i++) {
			accountInfoNode = accountInfoList.item(i);
			
			if (accountInfoNode == null || !accountInfoNode.getNodeName().equalsIgnoreCase("account-info")) {
				new NackRequest(com).send(m, 4, "Unable to find account-info element at " + i + ".", originator);
				return false;
			}
			
			nameNode = accountInfoNode.getAttributes().getNamedItem("name");
			
			if (nameNode == null) {
				new NackRequest(com).send(m, 4, "Unable to find name attribute at " + i + ".", originator);
				return false;
			}
			
			passwordNode = accountInfoNode.getAttributes().getNamedItem("password");
			
			if (passwordNode == null) {
				new NackRequest(com).send(m, 4, "Unable to find password attribute at " + i + ".", originator);
				return false;
			}
			
			toAdd.add(new User(nameNode.getNodeValue(), passwordNode.getNodeValue()));
		}
		
		Vector<String> successfullyAddedUsers = new Vector<String>();
		Vector<String> unsuccessfullyAddedUsers = new Vector<String>();
		Vector<String> preexistingUsers = new Vector<String>();
		
		for (User u : toAdd) {
			if (um.getUser(u.getName()) != null)
				preexistingUsers.add(u.getName());
			else if (um.addUser(u))
				successfullyAddedUsers.add(u.getName());
			else
				unsuccessfullyAddedUsers.add(u.getName());
		}
		
		String message = "";
		
		if (successfullyAddedUsers.size() > 0)
			message += "Successfully added " + successfullyAddedUsers.size() + " users. ";
		if (preexistingUsers.size() > 0) {
			message += "The following users already exist: ";
			for (String u : preexistingUsers)
				message += u + ",";
			message = message.substring(0, message.length()-1);
			message += ". ";
		}
		if (unsuccessfullyAddedUsers.size() > 0) {
			message += "The following users could not be added to the database: ";
			for (String u : unsuccessfullyAddedUsers)
				message += u + ",";
			message = message.substring(0, message.length()-1);
			message += ".";
		}
		
		if (successfullyAddedUsers.size() == 0) {
			new NackRequest(com).send(m, 4, message, originator);
			return false;
		}
		
		new AckRequest(com).send(m, message, originator);
		return true;
	}
}
